﻿using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Fast.Extensions.Caching.StackExchangeRedis
{
    public class FastRedisCache : RedisCache, ICacheSupportsMultipleItems
    {
        public FastRedisCache(IOptions<RedisCacheOptions> optionsAccessor)
            : base(optionsAccessor)
        {

        }
        /// <summary>
        /// 获取指定缓存键的多个缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <returns></returns>
        public byte[][] GetMany(
            IEnumerable<string> keys
        )
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            try
            {
                return keys.Select(key => Get(key)).ToArray();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 获取指定缓存键的多个缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        public async Task<byte[][]> GetManyAsync(
            IEnumerable<string> keys,
            CancellationToken token = default
        )
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            try
            {
                var result = new List<byte[]>();

                foreach (var key in keys)
                {
                    result.Add(await GetAsync(key, token));
                }

                return result.ToArray();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 设置多个缓存项
        /// </summary>
        /// <param name="items">要在缓存上设置的项</param>
        /// <param name="options">值的缓存选项</param>
        public void SetMany(
            IEnumerable<KeyValuePair<string, byte[]>> items,
            DistributedCacheEntryOptions options
        )
        {
            try
            {
                foreach (var item in items)
                {
                    Set(item.Key, item.Value, options);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 设置多个缓存项
        /// </summary>
        /// <param name="items">要在缓存上设置的项</param>
        /// <param name="options">值的缓存选项</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        public async Task SetManyAsync(
            IEnumerable<KeyValuePair<string, byte[]>> items,
            DistributedCacheEntryOptions options,
            CancellationToken token = default
        )
        {
            try
            {
                foreach (var item in items)
                {
                    await SetAsync(item.Key, item.Value, options, token);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 刷新指定缓存键的缓存值，并重置其滑动过期超时
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        public void RefreshMany(
            IEnumerable<string> keys
        )
        {
            try
            {
                foreach (var key in keys)
                {
                    Refresh(key);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 刷新指定缓存键的缓存值，并重置其滑动过期超时
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        public async Task RefreshManyAsync(
            IEnumerable<string> keys,
            CancellationToken token = default
        )
        {
            try
            {
                foreach (var key in keys)
                {
                    await RefreshAsync(key, token);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 从缓存中删除指定缓存键的缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        public void RemoveMany(
            IEnumerable<string> keys
        )
        {
            try
            {
                var keyArray = keys.ToArray();
                foreach (var key in keyArray)
                {
                    Remove(key);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 从缓存中删除指定缓存键的缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        public async Task RemoveManyAsync(
            IEnumerable<string> keys,
            CancellationToken token = default
        )
        {
            try
            {
                var keyArray = keys.ToArray();
                foreach (var key in keyArray)
                {
                    await RemoveAsync(key, token);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}
